1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.collect;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkNotNull;
21
22 import com.google.common.annotations.GwtCompatible;
23 import com.google.common.annotations.GwtIncompatible;
24
25 import java.io.IOException;
26 import java.io.ObjectInputStream;
27 import java.io.ObjectOutputStream;
28 import java.util.EnumMap;
29 import java.util.Map;
30
31
32
33
34
35
36
37
38
39
40
41
42
43 @GwtCompatible(emulated = true)
44 public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
45 extends AbstractBiMap<K, V> {
46 private transient Class<K> keyType;
47 private transient Class<V> valueType;
48
49
50
51
52
53
54
55
56 public static <K extends Enum<K>, V extends Enum<V>> EnumBiMap<K, V>
57 create(Class<K> keyType, Class<V> valueType) {
58 return new EnumBiMap<K, V>(keyType, valueType);
59 }
60
61
62
63
64
65
66
67
68
69
70
71 public static <K extends Enum<K>, V extends Enum<V>> EnumBiMap<K, V>
72 create(Map<K, V> map) {
73 EnumBiMap<K, V> bimap = create(inferKeyType(map), inferValueType(map));
74 bimap.putAll(map);
75 return bimap;
76 }
77
78 private EnumBiMap(Class<K> keyType, Class<V> valueType) {
79 super(WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
80 WellBehavedMap.wrap(new EnumMap<V, K>(valueType)));
81 this.keyType = keyType;
82 this.valueType = valueType;
83 }
84
85 static <K extends Enum<K>> Class<K> inferKeyType(Map<K, ?> map) {
86 if (map instanceof EnumBiMap) {
87 return ((EnumBiMap<K, ?>) map).keyType();
88 }
89 if (map instanceof EnumHashBiMap) {
90 return ((EnumHashBiMap<K, ?>) map).keyType();
91 }
92 checkArgument(!map.isEmpty());
93 return map.keySet().iterator().next().getDeclaringClass();
94 }
95
96 private static <V extends Enum<V>> Class<V> inferValueType(Map<?, V> map) {
97 if (map instanceof EnumBiMap) {
98 return ((EnumBiMap<?, V>) map).valueType;
99 }
100 checkArgument(!map.isEmpty());
101 return map.values().iterator().next().getDeclaringClass();
102 }
103
104
105 public Class<K> keyType() {
106 return keyType;
107 }
108
109
110 public Class<V> valueType() {
111 return valueType;
112 }
113
114 @Override
115 K checkKey(K key) {
116 return checkNotNull(key);
117 }
118
119 @Override
120 V checkValue(V value) {
121 return checkNotNull(value);
122 }
123
124
125
126
127
128 @GwtIncompatible("java.io.ObjectOutputStream")
129 private void writeObject(ObjectOutputStream stream) throws IOException {
130 stream.defaultWriteObject();
131 stream.writeObject(keyType);
132 stream.writeObject(valueType);
133 Serialization.writeMap(this, stream);
134 }
135
136 @SuppressWarnings("unchecked")
137 @GwtIncompatible("java.io.ObjectInputStream")
138 private void readObject(ObjectInputStream stream)
139 throws IOException, ClassNotFoundException {
140 stream.defaultReadObject();
141 keyType = (Class<K>) stream.readObject();
142 valueType = (Class<V>) stream.readObject();
143 setDelegates(
144 WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
145 WellBehavedMap.wrap(new EnumMap<V, K>(valueType)));
146 Serialization.populateMap(this, stream);
147 }
148
149 @GwtIncompatible("not needed in emulated source.")
150 private static final long serialVersionUID = 0;
151 }